/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"

#include "ui组件构建结构.h"
#include "框架/屏幕.h"

#include "框架/工作区/节点视口/节点视口工作区.h"
#include "框架/工作区/3D工作区/3D视口工作区.h"
#include "框架/工作区/2D视口/2D视口工作区.h"
#include "框架/工作区/渲染器视口/渲染器视口工作区.h"
#include "框架/工作区/时间轴视口/轴视口工作区.h"

#include "框架/工作区/节点视口/ui渲染合成节点菜单.h"
#include "框架/工作区/设置窗口/设置视口工作区.h"
///#include "框架/工作区/渲染器视口/ui渲染合成节点菜单.h"
#include "渲染/渲染.h"


typedef void(*fun_组件保存函数)(FILE* f, C_Widget* self, S_组件构建& ob);
typedef C_Widget*(*fun_组件加载函数)(FILE* f, S_UI创建环境& ctx, S_组件构建& ob);

static std::map<std::string, fun_组件保存函数> g组件保存函数;
static std::map<std::string, fun_组件加载函数> g组件加载函数;





//===================================== 页面 ==========================================
static void f_工作区页面组件保存(FILE* f, C_Widget* self, S_组件构建& ob) {
	C_工作区页面* 工作区页面 = static_cast<C_工作区页面*>(self);
	fwrite(&工作区页面->m_工作区类型, sizeof(E_工作区类型), 1, f);
	fwrite(&工作区页面->m_是否延展, sizeof(bvec2), 1, f);

	switch (工作区页面->m_工作区类型) {
	case E_工作区类型::e_3D视口:
		f_3D视口工作区_保存工作区状态(f, 工作区页面);
		break;
	case E_工作区类型::e_2D视口:
		f_2D视口工作区_保存工作区状态(f, 工作区页面);
		break;
	case e_视频纹理:
		break;
	case e_曲线视口:
		break;
	case e_时间轴:
		break;
	case e_节点视口:
		f_物体节点工作区_保存工作区状态(f, 工作区页面);
		break;
	case e_材质节点视口:
		break;
	case e_渲染合成视口:
		f_渲染器视口工作区_保存工作区状态(f, 工作区页面);
		break;
	case e_文本编辑视口:
		break;
	default:
		break;
	}
	//ob.f_保存UI结构(f, self->m_子部件);
}

static C_Widget* f_工作区页面组件加载(FILE* f, S_UI创建环境& ctx, S_组件构建& ob) {
	E_工作区类型 type;
	fread(&type, sizeof(E_工作区类型), 1, f);
	auto* 工作区页面 = f_屏幕_create工作区页面(ctx, type);
	fread(&工作区页面->m_是否延展, sizeof(bvec2), 1, f);
	

	switch (type) {
	case e_3D视口:
		f_3D视口工作区_加载工作区状态(f, 工作区页面);
		break;
	case E_工作区类型::e_2D视口:
		f_2D视口工作区_加载工作区状态(f, 工作区页面);
		break;
	case e_视频纹理:
		break;
	case e_曲线视口:
		break;
	case e_时间轴:
		break;
	case e_节点视口:
		f_物体节点工作区_加载工作区状态(f, 工作区页面);
		break;
	case e_材质节点视口:
		break;
	case e_渲染合成视口:
		f_渲染器视口工作区_加载工作区状态(f, 工作区页面);
		break;
	case e_文本编辑视口:
		break;
	default:
		break;
	}

	return 工作区页面;
}




//===================================== 工作区 ==========================================
static void f_工作区组件保存(FILE* f, C_Widget* self, S_组件构建& ob) {
	//ob.f_保存UI结构(f, self);
	E_方向 方向 = f_ui_get多页面标签方向(self);
	fwrite(&方向, sizeof(E_方向), 1, f);

	auto ws = f_ui_get多页面所有页面(self);
	ob.f_保存UI结构(f, ws);

}

static C_Widget* f_工作区组件加载(FILE* f, S_UI创建环境& ctx, S_组件构建& ob) {
	E_方向 方向;
	fread(&方向, sizeof(E_方向), 1, f);

	auto* 工作区 = f_屏幕_创建工作区(ctx, 方向);

	std::vector<C_Widget*> ws = ob.f_加载UI结构(f, ctx);
	
	for (auto& w : ws) {
		f_屏幕_添加工作区页面(工作区, static_cast<C_工作区页面*>(w));
	}
	return 工作区;
}




//========================== 分割窗口 ==========================
static void f_分割窗口组件保存(FILE* f, C_Widget* self, S_组件构建& ob) {
	E_方向 方向 = f_ui_get分割框排列方向(self);
	std::vector<float32> 分割比 = f_ui_get分割框分割比例(self);

	fwrite(&方向, sizeof(E_方向), 1, f);
	fwrite(&self->m_是否延展, sizeof(bvec2), 1, f);
	file_写入序列到文件(f, 分割比);

	auto ws = f_ui_get分割框页面组件(self);
	ob.f_保存UI结构(f, ws);

}

static C_Widget* f_分割窗口组件加载(FILE* f, S_UI创建环境& ctx, S_组件构建& ob) {
	E_方向 方向;
	std::vector<float32> 分割比;
	bvec2 是否延展;

	fread(&方向, sizeof(E_方向), 1, f);
	fread(&是否延展, sizeof(bvec2), 1, f);
	file_读取序列到文件(f, &分割比);

	std::vector<C_Widget*> ws = ob.f_加载UI结构(f, ctx);

	auto* 分割窗口 = f_ui_创建分割窗口(ws, 方向, 分割比, ctx);
	分割窗口->m_是否延展 = 是否延展;
	return 分割窗口;
}



//========================= 主菜单 =============================
static void f_主菜单组件保存(FILE* f, C_Widget* self, S_组件构建& ob) {
	C_菜单* 主菜单 = static_cast<C_菜单*>(self);
	//fwrite(&工作区页面->m_工作区类型, sizeof(E_工作区类型), 1, f);
	//ob.f_保存UI结构(f, self);
}

static C_Widget* f_主菜单组件加载(FILE* f, S_UI创建环境& ctx, S_组件构建& ob) {
	//fread(&type, sizeof(E_工作区类型), 1, f);
	auto* 主菜单 = f_界面构建_主菜单创建(ctx);
	//std::vector<C_Widget*> ws = ob.f_加载UI结构(f, ctx);
	return 主菜单;
}



//========================= 布局 =============================
static void f_保存根分割布局(FILE* f, C_Widget* self, S_组件构建& ob) {
	fwrite(&self->m_布局方式, sizeof(E_布局方式), 1, f);
	//fwrite(&self->m_是否延展, sizeof(bvec2), 1, f);
	//auto 分割比例 = f_ui_get分割框分割比例(self);
	auto e = self->f_get更新部件();

	ob.f_保存UI结构(f, self->m_子组件);

}

static C_Widget* f_加载根分割布局(FILE* f, S_UI创建环境& ctx, S_组件构建& ob) {
	E_布局方式	方式;
	//bvec2		延展;
	fread(&方式, sizeof(E_布局方式), 1, f);
	
	auto ui_root = f_创建根部件({ 0.2, 0.2 }, { 0.8, 0.8 }, 方式);
	//file_写入序列到文件(f, 分割比例);
	
	auto ws = ob.f_加载UI结构(f, ctx);
	f_widget_添加子组件(ui_root, ws);

	return ui_root;
}



static void f_保存对话框(FILE* f, C_Widget* self, S_组件构建& ob) {
	f_file_保存字符串(f, L"对话框");
}

static C_Widget* f_加载对话框(FILE* f, S_UI创建环境& ctx, S_组件构建& ob) {
	std::wstring 对话框;
	对话框 = f_file_读取字符串(f);

	return S_框架::g_ui文件对话框;
}



S_组件构建::S_组件构建() {
	L"多页面";
	L"分割框";

	static bool 以初始化函数指针 = false;
	if (!以初始化函数指针) {
		g组件保存函数[DEF_WIDGET_根布局] = f_保存根分割布局;
		g组件加载函数[DEF_WIDGET_根布局] = f_加载根分割布局;

		g组件保存函数["分割框"] = f_分割窗口组件保存;
		g组件加载函数["分割框"] = f_分割窗口组件加载;

		g组件保存函数["主菜单"] = f_主菜单组件保存;
		g组件加载函数["主菜单"] = f_主菜单组件加载;

		g组件保存函数["工作区"] = f_工作区组件保存;
		g组件加载函数["工作区"] = f_工作区组件加载;

		g组件保存函数["工作区页面"] = f_工作区页面组件保存;
		g组件加载函数["工作区页面"] = f_工作区页面组件加载;

		g组件保存函数["对话框"] = f_保存对话框;
		g组件加载函数["对话框"] = f_加载对话框;

		以初始化函数指针 = true;
	}
	
}

void S_组件构建::f_保存UI结构(FILE* f, const std::vector<C_Widget*>& ws) {

	uint32 num = ws.size();
	fwrite(&num, sizeof(uint32), 1, f);
	//auto e = w->f_get更新部件();
	for (uint32 i = 0; i < num; ++i) {
		if (g组件保存函数.find(ws[i]->m_TypeName) != g组件保存函数.end()) {
			f_file_保存字符串(f, ws[i]->m_TypeName);
			g组件保存函数[ws[i]->m_TypeName](f, ws[i], *this);
		}
	}
}

std::vector<C_Widget*> S_组件构建::f_加载UI结构(FILE* f, S_UI创建环境& ctx) {
	std::vector<C_Widget*> ws;

	uint32 num = 0;
	fread(&num, sizeof(uint32), 1, f);
	
	for (uint32 i = 0; i < num; ++i) {
		std::string name = f_读取字符串(f);

		if (g组件保存函数.find(name) != g组件保存函数.end()) {
			C_Widget* w = g组件加载函数[name](f, ctx, *this);
			ws.push_back(w);
		}
	}

	return ws;
}


void S_组件构建::f_保存界面框架(FILE* f) {
	f_保存UI结构(f, S_框架::g_UIGM->m_根部件切换组);

}

void S_组件构建::f_加载界面框架(FILE* f) {
	S_框架::g_UIGM->m_UICtx->m_3DViewScene.clear();

	f_时间轴页面_销毁();


	auto tmpWidget = S_框架::g_UIGM->m_根部件切换组;

	for (auto& window : S_框架::g_主窗口) {
		window->f_清除UI();
		auto ws = f_加载UI结构(f, *window->m_UIctx);
		window->f_安装UI(ws.front());
	}
	f_ui_管理器添加根部件(S_框架::g_UIGM, S_框架::g_ui文件对话框);

	auto it = tmpWidget.begin();
	for (; it != tmpWidget.end();) {
		if ((*it)->m_TypeName == "对话框") {
			it = tmpWidget.erase(it);
		}
		else {
			++it;
		}
	}
	
	f_widget_push待销毁部件(tmpWidget.data(), tmpWidget.size());
	C_Widget::g_焦点数量 = 0;
}




void S_组件构建::f_构建默认界面(FILE* f, C_Widget* root) {

}

C_菜单* f_界面构建_主菜单创建(S_UI创建环境& ctx) {
	auto ui主菜单 = new C_菜单(E_方向::e_横向, ctx);
	ui主菜单->m_TypeName = "主菜单";
	
	S_菜单创建参数 子菜单{
		(fp_on_菜单项点击)0, {
			{L"打开", "文件", 0},
			{L"新建", "文件", 0},
			{L"另存", "文件", 0},
			{L"引入", "", 0},
			{L"追加", "", 0},
			{L"导入", "", 0},
			{ L"导出", "", 0 },
			{ L"退出", "", 0 },
		}
	};

	S_菜单创建参数 子菜单1{
			(fp_on_菜单项点击)0, {
			{L"打开", "", 0},
			{L"新建", "", 0},
			{L"另存", "", 0},
			{L"引入", "", 0},
			{L"追加", "", 0},
			{L"导入", "", 0},
			{L"导出", "", 0},
			{L"退出", "", &子菜单},
		}
	};

	S_菜单创建参数 子菜单2{
			(fp_on_菜单项点击)0, {
			{L"打开", "", 0},
			{L"新建", "", 0},
			{L"另存", "", 0},
			{L"引入", "", 0},
			{L"追加", "", 0},
			{L"导入", "", 0},
			{L"导出", "", 0},
			{L"退出", "", &子菜单1},
		}
	};

	S_菜单创建参数 编辑菜单{
			(fp_on_菜单项点击)0, {
			{L"撤销", "", 0},
			{L"重做", "", 0},
			{L"历史", "", 0},
			{L"重复上一步", "", 0},
			{L"重复下一步", "", 0},
			{L"设置", "", 0},
		}
	};

	S_菜单创建参数 渲染菜单{
			(fp_on_菜单项点击)0, {
			{L"渲染单帧", "", 0},
			{L"渲染序列", "", 0},
		}
	};

	S_菜单创建参数 窗口菜单{
			on_重载渲染器菜单项, {
			{L"渲染单帧", "", 0},
			{L"渲染序列", "", 0},
		{L"", "", 0},
			{L"节点离线更新", "", 0},
		}
	};

	S_菜单创建参数 配置菜单{
			on_配置菜单项, {
			{L"设置", "", 0},
			//{L"设置", "", 0},
		}
	};



	S_菜单创建参数 文件菜单 = {
			on_文件菜单项, {
			{L"打开", "folder_open", 0},
			{L"保存", "07", 0},
			{L"新建", "doc_new", 0},
			{L"另存", "doc_plus", 0},
			{L"引入", "inbox", &子菜单2},
			{L"追加", "doc_plus", 0},
			{L"导入", "import", 0},
			{L"导出", "export", 0},
			{L"退出", "doc_plus", 0},
			{L"测试导入场景", "", 0},
			{L"测试导入场景n2", "", 0},
		}
	};

	f_ui_添加菜单项(ui主菜单,
		{
			(fp_on_菜单项点击)0, {
				{L"文件", "", &文件菜单},
				{L"编辑", "", &编辑菜单},
				//{L"项目", "", &渲染菜单},
				{L"渲染", "", &窗口菜单},
				{L"配置", "", &配置菜单},
				//{L"帮助", "", 0},
				{L"关于", "", 0},
			}
		}
		,
		ctx
		,
		0
	);

	return ui主菜单;
}
